<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="gwmag" id="gwmag"><span data-lake-id="u3c7476d5" id="u3c7476d5">典型回答</span></h1>
  <p data-lake-id="u8b2748e9" id="u8b2748e9"><br></p>
  <p data-lake-id="u24bbbdcb" id="u24bbbdcb"><span data-lake-id="u5f97873b" id="u5f97873b">MySQL的Buffer Pool是一个内存区域，用于缓存数据页，从而提高查询性能。读写过程涉及到数据的从磁盘到内存的读取，以及在内存中的修改和写回磁盘。</span></p>
  <p data-lake-id="ued0a12ff" id="ued0a12ff"><span data-lake-id="u966e76de" id="u966e76de">​</span><br></p>
  <p data-lake-id="ud8612bd4" id="ud8612bd4"><br></p>
  <h3 data-lake-id="BRhla" id="BRhla"><span data-lake-id="u05888dfa" id="u05888dfa">读过程</span></h3>
  <p data-lake-id="udfac3d84" id="udfac3d84"><br></p>
  <p data-lake-id="u3e689507" id="u3e689507"><span data-lake-id="u7662c641" id="u7662c641">当我们在MySQL执行一个查询请求的时候，他的过程是这样的：</span></p>
  <p data-lake-id="ubad9c553" id="ubad9c553"><br></p>
  <ol list="u678345d1">
   <li fid="uc2e431da" data-lake-id="ufef1900a" id="ufef1900a"><span data-lake-id="u511e7f79" id="u511e7f79">MySQL首先检查Buffer Pool中是否存在本次查询的数据。如果数据在Buffer Pool中，就直接返回结果。</span></li>
   <li fid="uc2e431da" data-lake-id="uea640135" id="uea640135"><span data-lake-id="u896855cf" id="u896855cf">如果数据不在Buffer Pool中，MySQL会从磁盘读取数据。</span></li>
   <li fid="uc2e431da" data-lake-id="u0449eb3a" id="u0449eb3a"><span data-lake-id="u79ae8354" id="u79ae8354">读取的数据页被放入Buffer Pool，同时MySQL会返回请求的数据给应用程序。</span></li>
  </ol>
  <p data-lake-id="u29eceb49" id="u29eceb49"><span data-lake-id="ub3f65605" id="ub3f65605">​</span><br></p>
  <p data-lake-id="u764cc2f0" id="u764cc2f0"><span data-lake-id="u70f80c9c" id="u70f80c9c">读的过程比较简单的，而Buffer Pool的写的过程就有点复杂了</span></p>
  <p data-lake-id="u4aa5fdeb" id="u4aa5fdeb"><span data-lake-id="u03e93ed3" id="u03e93ed3">​</span><br></p>
  <h3 data-lake-id="iakZj" id="iakZj"><span data-lake-id="u935f7871" id="u935f7871">写过程</span></h3>
  <p data-lake-id="ue211dfc2" id="ue211dfc2"><br></p>
  <p data-lake-id="u4cc2127b" id="u4cc2127b"><span data-lake-id="udbd2e920" id="udbd2e920">当我们执行一次更新语句，如INSERT、UPDATE或DELETE等时，会进行以下过程</span></p>
  <p data-lake-id="u2fb7e83d" id="u2fb7e83d"><br></p>
  <ol list="u68cde8e7">
   <li fid="u80b18aeb" data-lake-id="u6be83011" id="u6be83011"><span data-lake-id="ud6fce797" id="ud6fce797">当应用程序执行写操作时，MySQL首先将要修改的数据页加载到Buffer Pool中。</span></li>
   <li fid="u80b18aeb" data-lake-id="uf847dfc4" id="uf847dfc4"><span data-lake-id="u90acdac9" id="u90acdac9">在Buffer Pool中，对数据页进行修改，以满足写请求。这些修改只在内存中进行，不会立即写回磁盘。</span></li>
   <li fid="u80b18aeb" data-lake-id="u2b9c5b01" id="u2b9c5b01"><span data-lake-id="u6f4d53cd" id="u6f4d53cd">如果Buffer Pool中的数据页被修改过，MySQL会将这个页标记为“脏页”（Dirty Page）。</span></li>
   <li fid="u80b18aeb" data-lake-id="u8375e9f6" id="u8375e9f6"><span data-lake-id="uc42618e9" id="uc42618e9">脏页被写回磁盘，此时写入操作完成，数据持久化。</span></li>
  </ol>
  <p data-lake-id="u9157e836" id="u9157e836"><br></p>
  <p data-lake-id="u2a03ccff" id="u2a03ccff"><span data-lake-id="uc7d4e8c0" id="uc7d4e8c0">但是需要注意的是，脏页写回磁盘是由一个后台线程进行的，在MySQL服务器空闲或负载较低时，InnoDB会进行脏页刷盘，以减少对用户线程的影响，降低对性能的影响。（</span><a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-pool-flushing.html" target="_blank" data-lake-id="u2f535483" id="u2f535483"><span data-lake-id="uc9fc19a3" id="uc9fc19a3">https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-pool-flushing.html</span></a><span data-lake-id="ucaf75239" id="ucaf75239"> ）</span></p>
  <p data-lake-id="u9f002506" id="u9f002506"><span data-lake-id="u598dcd7f" id="u598dcd7f">​</span><br></p>
  <p data-lake-id="ud2d6c6f5" id="ud2d6c6f5"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1692360052478-7a123e12-d590-438f-9abd-c968f0b7b2bb.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_36%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="u56a6e16f" id="u56a6e16f">（图源自：</span><span data-lake-id="u2a2876f8" id="u2a2876f8">）</span></p>
  <p data-lake-id="ud2f7c383" id="ud2f7c383"><span data-lake-id="u80198eae" id="u80198eae">​</span><br></p>
  <p data-lake-id="u9160e709" id="u9160e709"><span data-lake-id="ucd7a3c8f" id="ucd7a3c8f">当脏页的百分比达到innodb_max_dirty_pages_pct_lwm变量定义的低水位标记时，将启动缓冲池刷新。缓冲池页的默认低水位标记为10%。innodb_max_dirty_pages_pct_lwm值设为0会禁用这种提前刷新行为。</span></p>
  <p data-lake-id="uc1944aec" id="uc1944aec"><span data-lake-id="u253e43b8" id="u253e43b8" class="lake-fontsize-12" style="color: rgb(15, 15, 15)">​</span><br></p>
  <p data-lake-id="u6808128d" id="u6808128d"><span data-lake-id="u1cc60391" id="u1cc60391">InnoDB还使用了一种适应性刷新算法，根据redo log的生成速度和当前的刷新率动态调整刷新速度。其目的是通过确保刷新活动与当前工作负载保持同步，来平滑整体性能。</span></p>
  <p data-lake-id="u6895acd5" id="u6895acd5"><span data-lake-id="u40169d71" id="u40169d71">​</span><br></p>
  <p data-lake-id="udf388388" id="udf388388"><span data-lake-id="u9b582258" id="u9b582258">当然，我们页可以手动触发脏页的刷新到磁盘，例如通过执行SET GLOBAL innodb_buffer_pool_dump_now=ON 来进行一次脏页刷新。</span></p>
  <p data-lake-id="u8a0108e6" id="u8a0108e6"><span data-lake-id="u3f7ad733" id="u3f7ad733">​</span><br></p>
  <p data-lake-id="u874211a5" id="u874211a5"><span data-lake-id="u39ac39da" id="u39ac39da">还有一种情况，就是在MySQL服务器正常关闭或重启时，所有的脏页都会被刷新到磁盘。这样才能保证数据可以持久化下来。</span></p>
  <p data-lake-id="u746cb129" id="u746cb129"><span data-lake-id="u4cdddf5a" id="u4cdddf5a">​</span><br></p>
  <p data-lake-id="u8594d66d" id="u8594d66d"><span data-lake-id="u7879173a" id="u7879173a">​</span><br></p>
 </body>
</html>